
#region Using Statements

    using System;
    using System.Collections.Generic;
    using System.Linq;

    using System.Diagnostics;
    using System.Text;

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Media;
    using Microsoft.Xna.Framework.Net;
    using Microsoft.Xna.Framework.Storage;

#endregion

namespace HumanElement.Xna.Construct
{
    /// <summary>
    /// This is the Game Host class for the Construct Design Time game
    /// development tools.
    /// </summary>
    public class GameEngine : Game, IGame
    {
        private readonly Action<IGameHost>      _initializeDelegate;
        private readonly Action<ContentManager> _loadContentDelegate;
        private readonly Action<GameTime>       _updateDelegate;
        private readonly Action<GraphicsDevice> _drawDelegate;

        private SpriteBatch _spriteBatch;

        /// <summary>
        /// Gets the graphics.
        /// </summary>
        /// <value>The graphics.</value>
        public GraphicsDevice Graphics
        {
            get
            {
                return GraphicsDevice;
            }
        }

        /// <summary>
        /// Gets or sets the name of the test.
        /// </summary>
        /// <value>The name of the test.</value>
        public string Name
        {
            get;
            set;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="TestGame"/> class.
        /// </summary>
        public GameEngine() : base()
        {
                  
        }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="GameEngine"/> class.
        /// </summary>
        /// <param name="initializeDelegate">The initialize delegate.</param>
        /// <param name="loadContentDelegate">The load content delegate.</param>
        /// <param name="updateDelegate">The update delegate.</param>
        /// <param name="drawDelegate">The draw delegate.</param>
        /// <param name="name">The name.</param>
        public GameEngine(Action<IGameHost> initializeDelegate,
                        Action<ContentManager> loadContentDelegate,
                        Action<GameTime> updateDelegate,
                        Action<GraphicsDevice> drawDelegate,
                        string name) : this()
        {
            _initializeDelegate = initializeDelegate;
            _loadContentDelegate = loadContentDelegate;
            _updateDelegate = updateDelegate;
            _drawDelegate = drawDelegate;

            Name = name;
    
        }
                    

        /// <summary>
        /// Called after the Game and Graphics.GraphicsDevice are created, but before Game.LoadContent.
        /// Reference page contains code sample.
        /// </summary>
        protected override void Initialize()
        {                      
            base.Initialize();

            _spriteBatch = new SpriteBatch(GraphicsDevice);

            OnInitialize();
        }

        /// <summary>
        /// Called when the game has determined that game logic needs to be processed. Reference page contains links to related code samples.
        /// </summary>
        /// <param name="gameTime">Time passed since the last call to Microsoft.Xna.Framework.Game.Update(Microsoft.Xna.Framework.GameTime).</param>
        protected override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            OnUpdate(gameTime);
        }

        /// <summary>
        /// Called when graphics resources need to be loaded.
        /// </summary>
        protected override void LoadContent()
        {
            base.LoadContent();

            OnLoadContent(Content);
        }

        /// <summary>
        /// Called when the game determines it is time to draw a frame. Reference page contains code sample.
        /// </summary>
        /// <param name="gameTime">Time passed since the last call to Microsoft.Xna.Framework.Game.Draw(Microsoft.Xna.Framework.GameTime).</param>
        protected override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);

            OnDraw(Graphics);
        }

        /// <summary>
        /// Called when [load content].
        /// </summary>
        /// <param name="content">The content.</param>
        protected virtual void OnLoadContent(ContentManager content)
        {
            if(_loadContentDelegate != null)
            {
                _loadContentDelegate(content);
            }
        }

        /// <summary>
        /// Called when [initialize].
        /// </summary>
        protected virtual void OnLoadContent()
        {
            if(_loadContentDelegate != null)
            {
                _loadContentDelegate(this.Content);
            }
        }

        /// <summary>
        /// Called when [initialize].
        /// </summary>
        protected virtual void OnUpdate(GameTime gameTime)
        {
            if (_updateDelegate != null)
            {
                _updateDelegate(gameTime);
            }
        }

        /// <summary>
        /// Called when [initialize].
        /// </summary>
        protected virtual void OnInitialize()
        {
            if (_initializeDelegate != null)
            {
                _initializeDelegate(this.GameHost);
            }
        }

        /// <summary>
        /// Gets or sets the game host.
        /// </summary>
        /// <value>The game host.</value>
        public IGameHost GameHost
        {
            get;
            private set;
        }

        /// <summary>
        /// Called when [initialize].
        /// </summary>
        protected virtual void OnDraw(GraphicsDevice graphics)
        {
            if (_drawDelegate != null)
            {
                _drawDelegate(graphics);
            }
        }

        #region IInitialize Members

        /// <summary>
        /// Initializes the specified game host.
        /// </summary>
        /// <param name="game">The game.</param>
        public virtual void Initialize(IGame game)
        {
            
        }

        #endregion
    }
}
